JavaScript Module FederationãæŽ»çšããåçãã©ã°ã€ã³ã·ã¹ãã ã®æ§ç¯æ¹æ³ãæ¢ããŸããã¹ã±ãŒã©ãã«ã§ä¿å®æ§ã®é«ãã¢ããªã±ãŒã·ã§ã³ã®ããã®ã¢ãŒããã¯ãã£ãå®è£ ãã»ãã¥ãªãã£ããã¹ããã©ã¯ãã£ã¹ãåŠã³ãŸãã
JavaScript Module Federationãã©ã°ã€ã³ã¢ãŒããã¯ãã£ïŒåçãã©ã°ã€ã³ã·ã¹ãã ã®æ§ç¯
仿¥ã®è€éãªãŠã§ãéçºã®äžçã§ã¯ãã¢ãžã¥ãŒã«åŒã§ã¹ã±ãŒã©ãã«ããã€ä¿å®æ§ã®é«ãã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããšãäžå¯æ¬ ã§ãããããå®çŸããããã®åŒ·åãªææ³ã®1ã€ããã©ã°ã€ã³ã¢ãŒããã¯ãã£ã§ãããæ©èœã¯ç¬ç«ããåçã«ããŒããããã¢ãžã¥ãŒã«ã«åå²ãããŸããWebpack 5ã®æ©èœã§ããJavaScript Module Federationã¯ããã®ãããªã¢ãŒããã¯ãã£ãå®è£ ããããã®å ç¢ãªã¡ã«ããºã ãæäŸããŸãããã®èšäºã§ã¯ãModule Federationã䜿çšããŠåçãªãã©ã°ã€ã³ã·ã¹ãã ãæ§ç¯ããè€éãªè©³çްã«ã€ããŠæãäžããŠãããŸãã
Module Federationãšã¯ïŒ
Module Federationã¯ãJavaScriptã¢ããªã±ãŒã·ã§ã³ãå®è¡æã«ã³ãŒããåçã«å ±æããããšãå¯èœã«ããŸããããã¯ãããã¢ããªã±ãŒã·ã§ã³ã®ã¢ãžã¥ãŒã«ïŒã³ãŒãã®äžéšïŒããåãã«ããåãããã€ã®å¿ èŠãªããå¥ã®ã¢ããªã±ãŒã·ã§ã³ããçŽæ¥äœ¿çšã§ããããšãæå³ããŸããããã¯ãç°ãªããã«ããç°ãªããããã€ã¡ã³ãéã§ã¢ãžã¥ãŒã«ãå ¬éã»å©çšããããšã§å®çŸãããŸãã
npmããã±ãŒãžã®ãããªåŸæ¥ã®ã³ãŒãå ±ææ¹æ³ã§ã¯ãå ±æãããŠããäŸåé¢ä¿ãæŽæ°ããããã³ã«ããããå©çšããã¢ããªã±ãŒã·ã§ã³ãåãã«ãããã³åãããã€ããå¿ èŠããããŸãããModule Federationã¯ãã®ãªãŒããŒããããæé€ããé »ç¹ãªæŽæ°ãšç¬ç«ãããããã€ã¡ã³ããæ±ããããã·ããªãªã«æé©ã§ãã
ãªããã©ã°ã€ã³ã¢ãŒããã¯ãã£ã«Module Federationã䜿çšããã®ãïŒ
Module Federationã¯ããã©ã°ã€ã³ã¢ãŒããã¯ãã£ãæ§ç¯ããéã«ããã€ãã®å©ç¹ãæäŸããŸãïŒ
- åçãªã¢ãžã¥ãŒã«èªã¿èŸŒã¿: ãã©ã°ã€ã³ã¯å®è¡æã«èªã¿èŸŒã¿ã»ã¢ã³ããŒããå¯èœã§ãã¢ããªã±ãŒã·ã§ã³ãå®å šã«åãããã€ããããšãªããå€åããèŠä»¶ã«é©å¿ã§ããŸãã
- ãã«ãããªã³ã°: ãã©ã°ã€ã³ã¯ç¬ç«ããŠéçºã»ãããã€ããããããã¢ããªã±ãŒã·ã§ã³ã®ç°ãªãéšåéã®äŸåé¢ä¿ãæžå°ããŸãã
- ã¹ã±ãŒã©ããªãã£: æ¢åã®æ©èœã«åœ±é¿ãäžããããšãªããæ°ãããã©ã°ã€ã³ã§ã¢ããªã±ãŒã·ã§ã³ãç°¡åã«æ¡åŒµã§ããŸãã
- ä¿å®æ§: ãã©ã°ã€ã³ã¯ç¬ç«ããŠæŽæ°ã»ä¿å®ã§ãããããã³ã¢ã¢ããªã±ãŒã·ã§ã³ã«ãã°ãå°å ¥ãããªã¹ã¯ãäœæžãããŸãã
- ã³ãŒãã®åå©çš: ãã©ã°ã€ã³ã¯è€æ°ã®ã¢ããªã±ãŒã·ã§ã³éã§åå©çšã§ããäžè²«æ§ãä¿é²ããéçºå·¥æ°ãåæžããŸãã
- ããŒãžã§ãã³ã°ãšããŒã«ããã¯: ãã©ã°ã€ã³ã®ç°ãªãããŒãžã§ã³ã管çããå¿ èŠã«å¿ããŠä»¥åã®ããŒãžã§ã³ã«ç°¡åã«ããŒã«ããã¯ã§ããŸãã
ã³ã¢ã³ã³ã»ããïŒãã¹ãã³ã³ãããšãªã¢ãŒãã³ã³ãã
Module Federationã¯ã2ã€ã®äž»èŠãªã³ã³ã»ãããäžå¿ã«å±éãããŸãïŒ
- ãã¹ãã³ã³ãã: ãªã¢ãŒãã¢ãžã¥ãŒã«ïŒãã©ã°ã€ã³ïŒãå©çšããã¡ã€ã³ã¢ããªã±ãŒã·ã§ã³ã
- ãªã¢ãŒãã³ã³ãã: ãã¹ãã«ãã£ãŠå©çšãããã¢ãžã¥ãŒã«ïŒãã©ã°ã€ã³ïŒãå ¬éããã¢ããªã±ãŒã·ã§ã³ã
ãã¹ãã³ã³ããã¯ããªã¢ãŒãã³ã³ãããããªã¢ãŒããšã³ããªãŒãã¡ã€ã«ãåçã«ååŸããŸããããã«ã¯å ¬éãããŠããã¢ãžã¥ãŒã«ã®ãããã§ã¹ããå«ãŸããŠããŸãããã®åŸããã¹ãã¯ãããã®ã¢ãžã¥ãŒã«ãèªèº«ã®ã³ãŒãããŒã¹ã®äžéšã§ãããã®ããã«ã¢ã¯ã»ã¹ããŠäœ¿çšã§ããŸãã
Module Federationã«ããåçãã©ã°ã€ã³ã·ã¹ãã ã®å®è£ ïŒã¹ããããã€ã¹ãããã¬ã€ã
Module Federationã䜿çšããŠç°¡åãªãã©ã°ã€ã³ã·ã¹ãã ãæ§ç¯ããããã»ã¹ãèŠãŠãããŸãããããã¹ãã¢ããªã±ãŒã·ã§ã³ãšãªã¢ãŒããã©ã°ã€ã³ã¢ããªã±ãŒã·ã§ã³ãäœæããŸãã
1. ãã¹ãã¢ããªã±ãŒã·ã§ã³ã®ã»ããã¢ããïŒãã¹ãã³ã³ããïŒ
ãŸããæ°ãããããžã§ã¯ããã£ã¬ã¯ããªãäœæããæ°ããnpmãããžã§ã¯ããåæåããŸãïŒ
mkdir host-app
cd host-app
npm init -y
Webpackãšãã®äŸåé¢ä¿ãã€ã³ã¹ããŒã«ããŸãïŒ
npm install webpack webpack-cli webpack-dev-server html-webpack-plugin --save-dev
`host-app`ãã£ã¬ã¯ããªã«`webpack.config.js`ãã¡ã€ã«ãäœæããæ¬¡ã®èšå®ã远å ããŸãïŒ
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const path = require('path');
module.exports = {
mode: 'development',
devtool: 'source-map',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
devServer: {
port: 3000,
hot: true,
static: {
directory: path.join(__dirname, 'dist'),
},
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
},
},
},
],
},
plugins: [
new ModuleFederationPlugin({
name: 'Host',
remotes: {
'plugin': 'Plugin@http://localhost:3001/remoteEntry.js',
},
shared: ['react', 'react-dom'],
}),
new HtmlWebpackPlugin({
template: './public/index.html',
}),
],
};
解説ïŒ
- `name`: ãã¹ãã¢ããªã±ãŒã·ã§ã³ã®ååã
- `remotes`: ãã¹ããå©çšãããªã¢ãŒãã³ã³ãããå®çŸ©ããŸãããã®ã±ãŒã¹ã§ã¯ã`http://localhost:3001/remoteEntry.js` ãã `plugin` ãšããååã®ãªã¢ãŒãã³ã³ãããå©çšããŠããŸãã`Plugin@` ãšããæ§æã¯ããªã¢ãŒãã®ModuleFederationPluginã® `name` ã 'Plugin' ã§ããããšãæå³ããŸãã
- `shared`: ãã¹ããšãªã¢ãŒãã³ã³ããéã§å ±æãããäŸåé¢ä¿ããªã¹ãã¢ããããŸããããã«ããããããã®äŸåé¢ä¿ã®éè€ã³ããŒãããŒããããã®ãé²ããŸãã`shared` ã®äœ¿çšã¯ããšã©ãŒãåé¿ãããã©ã°ã€ã³ãé©åã«æ©èœããããšãä¿èšŒããããã«éåžžã«éèŠã§ãã
`src`ãã£ã¬ã¯ããªãäœæãã`index.js`ãã¡ã€ã«ã«æ¬¡ã®å 容ã远å ããŸãïŒ
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom/client';
const PluginComponent = React.lazy(() => import('plugin/PluginComponent'));
const App = () => {
return (
<div>
<h1>Host Application</h1>
<Suspense fallback={<div>Loading Plugin...</div>}>
<PluginComponent />
</Suspense>
</div>
);
};
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
解説ïŒ
- `React.lazy` ã䜿çšããŠã`plugin` ãªã¢ãŒããã `PluginComponent` ãåçã«ã€ã³ããŒãããŠããŸããããã¯ãã©ã°ã€ã³ãé å»¶èªã¿èŸŒã¿ããåæããŒãã®é å»¶ãé¿ããããã«äžå¯æ¬ ã§ãã
- `Suspense` ã³ã³ããŒãã³ãã¯ããã©ã°ã€ã³ããã§ãããããŠããéã®ããŒãã£ã³ã°ç¶æ ãåŠçããããã«äœ¿çšãããŸãã
`public`ãã£ã¬ã¯ããªãäœæãã`index.html`ãã¡ã€ã«ã«æ¬¡ã®å 容ã远å ããŸãïŒ
<!DOCTYPE html>
<html>
<head>
<title>Host Application</title>
</head>
<body>
<div id="root"></div>
<script src="./bundle.js"></script>
</body>
</html>
Babelã®èšå®ãã¡ã€ã« `.babelrc` ã远å ããŸãïŒ
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}
`package.json`ãæŽæ°ããŠãstartã¹ã¯ãªããã远å ããŸãïŒ
{
"name": "host-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack serve --mode development",
"build": "webpack --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.23.9",
"@babel/preset-env": "^7.23.9",
"@babel/preset-react": "^7.23.3",
"babel-loader": "^9.1.3",
"html-webpack-plugin": "^5.6.0",
"webpack": "^5.90.3",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}
2. ãªã¢ãŒãã¢ããªã±ãŒã·ã§ã³ã®ã»ããã¢ããïŒãã©ã°ã€ã³ã³ã³ããïŒ
ãã©ã°ã€ã³çšã®æ°ãããããžã§ã¯ããã£ã¬ã¯ããªãäœæããŸãïŒ
mkdir plugin-app
cd plugin-app
npm init -y
Webpackãšãã®äŸåé¢ä¿ãã€ã³ã¹ããŒã«ããŸãïŒ
npm install webpack webpack-cli webpack-dev-server html-webpack-plugin --save-dev
`plugin-app`ãã£ã¬ã¯ããªã«`webpack.config.js`ãã¡ã€ã«ãäœæããæ¬¡ã®èšå®ã远å ããŸãïŒ
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const path = require('path');
module.exports = {
mode: 'development',
devtool: 'source-map',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
devServer: {
port: 3001,
hot: true,
static: {
directory: path.join(__dirname, 'dist'),
},
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
},
},
},
],
},
plugins: [
new ModuleFederationPlugin({
name: 'Plugin',
filename: 'remoteEntry.js',
exposes: {
'./PluginComponent': './src/PluginComponent',
},
shared: ['react', 'react-dom'],
}),
new HtmlWebpackPlugin({
template: './public/index.html',
}),
],
};
解説ïŒ
- `name`: ãªã¢ãŒãã³ã³ããïŒãã©ã°ã€ã³ïŒã®ååãããã¯ãã¹ãã®`remotes`èšå®ã§äœ¿çšãããååãš**äžèŽããªããã°ãªããŸãã**ã
- `filename`: ãã¹ããååŸãããªã¢ãŒããšã³ããªãŒãã¡ã€ã«ã®ååã
- `exposes`: ãªã¢ãŒãã³ã³ããã«ãã£ãŠå ¬éãããã¢ãžã¥ãŒã«ãå®çŸ©ããŸãããã®ã±ãŒã¹ã§ã¯ã`PluginComponent`ã¢ãžã¥ãŒã«ãå ¬éããŠããŸããã㌠'./PluginComponent' ã¯ããã¹ãã®ã€ã³ããŒãæïŒäŸïŒ`import('plugin/PluginComponent')`ïŒã§äœ¿çšãããŸãã
- `shared`: ãã¹ããšåæ§ã«ãå ±æãããäŸåé¢ä¿ããªã¹ãã¢ããããŸããå ±æãããäŸåé¢ä¿ãšãã®ããŒãžã§ã³ããã¹ããšãªã¢ãŒãã§äºææ§ãããããšãéåžžã«éèŠã§ãã
`src`ãã£ã¬ã¯ããªãäœæãã`PluginComponent.jsx`ãã¡ã€ã«ã«æ¬¡ã®å 容ã远å ããŸãïŒ
import React from 'react';
const PluginComponent = () => {
return (
<div style={{border: '1px solid blue', padding: '10px'}}>
<h2>Plugin Component</h2>
<p>This is a dynamically loaded plugin!</p>
</div>
);
};
export default PluginComponent;
`src`ãã£ã¬ã¯ããªã«`index.js`ãã¡ã€ã«ãäœæããPluginComponentããšã¯ã¹ããŒãããŸãïŒ
import PluginComponent from './PluginComponent';
export default PluginComponent;
`public`ãã£ã¬ã¯ããªãäœæãã`index.html`ãã¡ã€ã«ã«æ¬¡ã®å 容ã远å ããŸãïŒ
<!DOCTYPE html>
<html>
<head>
<title>Plugin Application</title>
</head>
<body>
<div id="root"></div>
<script src="./bundle.js"></script>
</body>
</html>
Babelã®èšå®ãã¡ã€ã« `.babelrc` ã远å ããŸãïŒ
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}
`package.json`ãæŽæ°ããŠãstartã¹ã¯ãªããã远å ããŸãïŒ
{
"name": "plugin-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack serve --mode development",
"build": "webpack --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.23.9",
"@babel/preset-env": "^7.23.9",
"@babel/preset-react": "^7.23.3",
"babel-loader": "^9.1.3",
"html-webpack-plugin": "^5.6.0",
"webpack": "^5.90.3",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}
3. ã¢ããªã±ãŒã·ã§ã³ã®å®è¡
ãã¹ããšãã©ã°ã€ã³ã®äž¡æ¹ã®ã¢ããªã±ãŒã·ã§ã³ããããããã®ãã£ã¬ã¯ããªã§`npm start`ãå®è¡ããŠèµ·åããŸãã
ãã©ãŠã¶ã§`http://localhost:3000`ã«ã¢ã¯ã»ã¹ããŸããåçã«èªã¿èŸŒãŸãããã©ã°ã€ã³ã³ã³ããŒãã³ãã衚瀺ããããã¹ãã¢ããªã±ãŒã·ã§ã³ã衚瀺ãããã¯ãã§ãã
é«åºŠãªæ©èœãšèæ ®äºé
ããŒãžã§ãã³ã°ãšããŒã«ããã¯
Module Federationã¯ããŒãžã§ãã³ã°ããµããŒãããŠããããã©ã°ã€ã³ã®ç°ãªãããŒãžã§ã³ã管çã§ããŸãããã¹ãã®`remotes`èšå®ã§ããŒãžã§ã³å¶çŽãæå®ã§ããŸããäŸãã°ïŒ
remotes: {
'plugin': 'Plugin@http://localhost:3001/remoteEntry.js@1.0.0',
}
ããã«ããããã¹ãã¯ãã©ã°ã€ã³ã®ããŒãžã§ã³1.0.0ã䜿çšããããã«ãªããŸããæ°ããããŒãžã§ã³ãå©çšå¯èœã«ãªã£ãŠããæç€ºçã«æŽæ°ããããŸã§ãã¹ãã¯æå®ãããããŒãžã§ã³ã䜿ãç¶ããŸããå ç¢ãªããŒãžã§ãã³ã°ãå®è£ ããããšã¯ãç Žå£çãªå€æŽãé²ããã¢ããªã±ãŒã·ã§ã³ã®å®å®æ§ã確ä¿ããããã«äžå¯æ¬ ã§ãã
ã»ãã¥ãªãã£ã«é¢ããèæ ®äºé
Module Federationã䜿çšããéã«ã¯ãã»ãã¥ãªãã£ãæåªå äºé ã§ãã以äžãèæ ®ããŠãã ããïŒ
- èªèšŒãšèªå¯: é©åãªèªèšŒã»èªå¯ã¡ã«ããºã ãå®è£ ããèªå¯ããããŠãŒã¶ãŒã®ã¿ããã©ã°ã€ã³ã«ã¢ã¯ã»ã¹ã»äœ¿çšã§ããããã«ããŸãã
- ã³ãŒãã®å®å šæ§: ãªã¢ãŒãã¢ãžã¥ãŒã«ã®å®å šæ§ãæ€èšŒããæªæã®ããã³ãŒããã¢ããªã±ãŒã·ã§ã³ã«æ³šå ¥ãããã®ãé²ããŸããContent Security Policy (CSP) ã䜿çšããŠãã¢ããªã±ãŒã·ã§ã³ããªãœãŒã¹ãããŒãã§ãããœãŒã¹ãå¶éããããšãæ€èšããŠãã ããã
- äŸåé¢ä¿ã®ç®¡ç: è匱æ§ãé¿ããããããã¹ããšãªã¢ãŒãã³ã³ããã®äž¡æ¹ã®äŸåé¢ä¿ãæ éã«ç®¡çããŸãã宿çã«äŸåé¢ä¿ãææ°ããŒãžã§ã³ã«æŽæ°ããŸãã
- å ¥åæ€èšŒ: ã€ã³ãžã§ã¯ã·ã§ã³æ»æãé²ãããããªã¢ãŒãã¢ãžã¥ãŒã«ããåãåã£ããã¹ãŠã®ããŒã¿ãæ€èšŒããŸãã
- CORS (Cross-Origin Resource Sharing): ãã¹ãã¢ããªã±ãŒã·ã§ã³ããã©ã°ã€ã³ã¢ããªã±ãŒã·ã§ã³ãããªã¢ãŒããšã³ããªãŒãã¡ã€ã«ã«ã¢ã¯ã»ã¹ã§ããããã«ãCORSãé©åã«èšå®ããŸãã
ãã©ã°ã€ã³ã®çºèŠãšç®¡ç
ããè€éãªãã©ã°ã€ã³ã·ã¹ãã ã§ã¯ããã©ã°ã€ã³ãçºèŠã»ç®¡çããããã®ã¡ã«ããºã ãå¿ èŠã«ãªãå ŽåããããŸããããã¯ããã©ã°ã€ã³ã¬ãžã¹ããªããã£ã¹ã«ããªãŒãµãŒãã¹ãéããŠå®çŸã§ããŸããäžå€®ã¬ãžã¹ããªã«ã¯ãå©çšå¯èœãªãã©ã°ã€ã³ã«é¢ããæ å ±ïŒå ŽæãããŒãžã§ã³ãäŸåé¢ä¿ãªã©ïŒãä¿åã§ããŸãããã¹ãã¢ããªã±ãŒã·ã§ã³ã¯ããã®ã¬ãžã¹ããªã«åãåãããŠé©åãªãã©ã°ã€ã³ãèŠã€ããŠããŒãããããšãã§ããŸãã
以äžã®ã¢ãããŒããæ€èšããŠãã ããïŒ
- äžå€®éæš©çãªèšå®: ãã©ã°ã€ã³ã®URLãäžå€®ã®èšå®ãã¡ã€ã«ïŒäŸïŒJSONãã¡ã€ã«ïŒã«ä¿åãããã¹ãã¢ããªã±ãŒã·ã§ã³ãå®è¡æã«ãããèªã¿èŸŒã¿ãŸããããã«ããããã¹ãã¢ããªã±ãŒã·ã§ã³ãåãããã€ããããšãªãããã©ã°ã€ã³ãç°¡åã«è¿œå ãåé€ãæŽæ°ã§ããŸãã
- APIããŒã¹ã®çºèŠ: å©çšå¯èœãªãã©ã°ã€ã³ã®ãªã¹ããè¿ãAPIãšã³ããã€ã³ããäœæããŸãããã¹ãã¢ããªã±ãŒã·ã§ã³ã¯ããã®ãªã¹ããååŸããŠåçã«ãã©ã°ã€ã³ãããŒãã§ããŸãã
- ã€ãã³ãé§ååã¢ãŒããã¯ãã£: ã€ãã³ããã¹ãã¡ãã»ãŒãžãã¥ãŒã䜿çšããŠãæ°ãããã©ã°ã€ã³ãå©çšå¯èœã«ãªã£ããšãã«ãã¹ãã¢ããªã±ãŒã·ã§ã³ã«éç¥ããŸããããã«ãããéåæã§ã®ãã©ã°ã€ã³ã®çºèŠãšããŒããå¯èœã«ãªããŸãã
åçãªèšå®ãšãã©ã°ã€ã³ã®ã¢ã¯ãã£ããŒã·ã§ã³
ãŠãŒã¶ãŒãåçã«ãã©ã°ã€ã³ãèšå®ã»æå¹åã§ããããã«ããããšã¯åŒ·åãªæ©èœã§ããããã«ã¯ããã©ã°ã€ã³èšå®ãä¿åã»ç®¡çããã¡ã«ããºã ãå¿ èŠã§ããããŒã¿ããŒã¹ãèšå®ãã¡ã€ã«ããŸãã¯ã¯ã©ãŠãããŒã¹ã®èšå®ãµãŒãã¹ã䜿çšããŠãã©ã°ã€ã³èšå®ãä¿åã§ããŸãããã¹ãã¢ããªã±ãŒã·ã§ã³ã¯ãå®è¡æã«ãããã®èšå®ãèªã¿åããããã«å¿ããŠãã©ã°ã€ã³ãæå¹åã§ããŸãããã©ã°ã€ã³èšå®ã管çããããã®ãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ãŒã¹ãæäŸããããšãæ€èšããŠãã ããã
éåææäœãšãšã©ãŒãã³ããªã³ã°ã®åŠç
åçã«ããŒãããããã©ã°ã€ã³ãæ±ãéã«ã¯ãéåææäœãšãšã©ãŒãé©åã«åŠçããããšãäžå¯æ¬ ã§ãã`async/await`ãPromisesã䜿çšããŠéåæã³ãŒãã管çããŸãããã©ã°ã€ã³ã®ããŒãäžãå®è¡äžã«çºçãããšã©ãŒããã£ããããŠãã°ã«èšé²ããããã«ãé©åãªãšã©ãŒãã³ããªã³ã°ãå®è£ ããŸãããŠãŒã¶ãŒã«æçãªãšã©ãŒã¡ãã»ãŒãžãæäŸããŸãããã¹ãŠãã©ã°ã€ã³ã«ããã£ãŠãšã©ãŒã远跡ããããã«ãäžå€®éæš©çãªãšã©ãŒãã®ã³ã°ãµãŒãã¹ã®äœ¿çšãæ€èšããŠãã ããã
ã³ãŒãåå²ãšããã©ãŒãã³ã¹æé©å
ããã©ãŒãã³ã¹ãæé©åããããã«ãã³ãŒãåå²ã䜿çšããŠã¢ããªã±ãŒã·ã§ã³ãšãã©ã°ã€ã³ãããå°ããªãã£ã³ã¯ã«åå²ããŸããããã«ããããã©ãŠã¶ã¯ç¹å®ã®ããŒãžãæ©èœã«å¿ èŠãªã³ãŒãã®ã¿ãããŠã³ããŒãã§ããŸããWebpackã¯ã³ãŒãåå²ãçµã¿èŸŒã¿ã§ãµããŒãããŠããŸãããã©ã°ã€ã³ãå¿ èŠãªãšãã«ã®ã¿ããŒãããããã«ãé å»¶èªã¿èŸŒã¿ã®äœ¿çšãæ€èšããŠãã ããããã¡ã€ã«ãµã€ãºãåæžããããã«ãã³ãŒãããããã¡ã€ããã³å§çž®ããŸãã
ãã¹ããšç¶ç¶çã€ã³ãã°ã¬ãŒã·ã§ã³
ãã©ã°ã€ã³ã·ã¹ãã ãæ£ããåäœããããšã確èªããããã«ã培åºçã«ãã¹ãããŸãããŠããããã¹ããçµ±åãã¹ãããšã³ãããŒãšã³ããã¹ããäœæããŸããç¶ç¶çã€ã³ãã°ã¬ãŒã·ã§ã³ïŒCIïŒã·ã¹ãã ã䜿çšããŠãã³ãŒãã倿Žããããã³ã«èªåçã«ãã¹ããå®è¡ããŸããç¶ç¶çããªããªãŒïŒCDïŒãã€ãã©ã€ã³ãå®è£ ããŠãã¢ããªã±ãŒã·ã§ã³ãšãã©ã°ã€ã³ã®ãããã€ãèªååããŸãã
å®äžçã®äŸãšãŠãŒã¹ã±ãŒã¹
Module Federationã¯ã以äžãå«ãããŸããŸãªå®äžçã®ã¢ããªã±ãŒã·ã§ã³ã§äœ¿çšãããŠããŸãïŒ
- Eã³ããŒã¹ãã©ãããã©ãŒã : ååã®ãããããæ±ºæžã²ãŒããŠã§ã€ãé 鿥è ãåçã«èªã¿èŸŒã¿ãŸããäŸãã°ãã°ããŒãã«ãªEã³ããŒã¹ãã©ãããã©ãŒã ã¯ãé¡§å®¢ã®æåšå°ã«åºã¥ããŠç°ãªã決æžãããã€ããŒãçµ±åããããã«Module Federationã䜿çšã§ããŸããåç±³ã§ã¯Stripeã®ãã©ã°ã€ã³ãããšãŒãããã§ã¯PayPalãKlarnaã®ãã©ã°ã€ã³ãèªã¿èŸŒããããããŸããã
- ã³ã³ãã³ã管çã·ã¹ãã ïŒCMSïŒ: ãŠãŒã¶ãŒããã©ã°ã€ã³ãã€ã³ã¹ããŒã«ããŠæå¹åããCMSã®æ©èœãæ¡åŒµã§ããããã«ããŸããCMSã¯ãSEOæé©åããœãŒã·ã£ã«ã¡ãã£ã¢çµ±åããŸãã¯ã³ã³ãã³ãåæã®ããã®ãã©ã°ã€ã³ããŠãŒã¶ãŒãã€ã³ã¹ããŒã«ã§ããããã«ããããšãã§ããŸãã
- ããã·ã¥ããŒããšåæãã©ãããã©ãŒã : ããŸããŸãªãŠã£ãžã§ãããèŠèŠåãåçã«èªã¿èŸŒã¿ãŸããã°ããŒãã«ãªåæãã©ãããã©ãŒã ã¯ãGoogle AnalyticsãAdobe AnalyticsãSalesforceãªã©ãããŸããŸãªããŒã¿ãœãŒã¹çšã®ãã©ã°ã€ã³ãèªã¿èŸŒããããããŸããã
- ãã€ã¯ãããã³ããšã³ãã¢ãŒããã¯ãã£: å€§èŠæš¡ãªWebã¢ããªã±ãŒã·ã§ã³ããç¬ç«ããŠãããã€å¯èœãªãã€ã¯ãããã³ããšã³ãã®éåãšããŠæ§ç¯ããŸããå€§äŒæ¥ã¯ãã¢ã«ãŠã³ã管çã補åã«ã¿ãã°ã泚æåŠçãªã©ãç¹å®ã®ããžãã¹æ©èœãæ åœãããã€ã¯ãããã³ããšã³ãã®éåãšããŠWebã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã«Module Federationã䜿çšã§ããŸãã
- ãã¶ã€ã³ã·ã¹ãã : è€æ°ã®ã¢ããªã±ãŒã·ã§ã³éã§UIã³ã³ããŒãã³ããšãã¶ã€ã³ããŒã¯ã³ãå ±æããŸããè€æ°ã®ãã©ã³ããæã€ã°ããŒãã«çµç¹ã¯ããã¹ãŠã®ã¢ããªã±ãŒã·ã§ã³ã§å ±éã®ãã¶ã€ã³ã·ã¹ãã ãå ±æããããã«Module Federationã䜿çšããäžè²«æ§ã確ä¿ããéçºå·¥æ°ãåæžã§ããŸãã
Module Federationã§åçãã©ã°ã€ã³ã·ã¹ãã ãæ§ç¯ããããã®ãã¹ããã©ã¯ãã£ã¹
Module Federationã§åçãã©ã°ã€ã³ã·ã¹ãã ãæ§ç¯ããéã«çæãã¹ããã¹ããã©ã¯ãã£ã¹ãããã€ã玹ä»ããŸãïŒ
- ãã©ã°ã€ã³ãå°ãããçŠç¹ãçµã: åãã©ã°ã€ã³ã¯ç¹å®ã®æ©èœã«è²¬ä»»ãæã€ã¹ãã§ããããã«ããããã©ã°ã€ã³ã®ä¿å®ãšæŽæ°ã容æã«ãªããŸãã
- æç¢ºãªãã©ã°ã€ã³ã€ã³ã¿ãŒãã§ãŒã¹ãå®çŸ©ãã: ãã©ã°ã€ã³ããã¹ãã¢ããªã±ãŒã·ã§ã³ãšã©ã®ããã«å¯Ÿè©±ãããã®æç¢ºãªã€ã³ã¿ãŒãã§ãŒã¹ãå®çŸ©ããŸããããã«ããããã©ã°ã€ã³ããã¹ããšäºææ§ãããããšãä¿èšŒãããç Žå£çãªå€æŽãé²ããŸãã
- ã»ãã³ãã£ãã¯ããŒãžã§ãã³ã°ã䜿çšãã: ãã©ã°ã€ã³ã®ããŒãžã§ã³ã管çããããã«ã»ãã³ãã£ãã¯ããŒãžã§ãã³ã°ã䜿çšããŸããããã«ããã倿Žã®è¿œè·¡ãšäºææ§ã®ç¢ºä¿ã容æã«ãªããŸãã
- ããã¥ã¡ã³ããæäŸãã: ãã©ã°ã€ã³ã®ããã®æç¢ºã§ç°¡æœãªããã¥ã¡ã³ããæäŸããŸããããã«ããããŠãŒã¶ãŒã¯ãã©ã°ã€ã³ã®ã€ã³ã¹ããŒã«ãèšå®ãäœ¿çšæ¹æ³ãçè§£ãããããªããŸãã
- ã»ãã¥ãªãã£ã®ãã¹ããã©ã¯ãã£ã¹ãå®è£ ãã: ã¢ããªã±ãŒã·ã§ã³ãšãã©ã°ã€ã³ãè匱æ§ããä¿è·ããããã«ãã»ãã¥ãªãã£ã®ãã¹ããã©ã¯ãã£ã¹ã«åŸããŸãã
- ãã©ã°ã€ã³ã®ããã©ãŒãã³ã¹ãç£èŠãã: ããã«ããã¯ãç¹å®ããããã«ããã©ã°ã€ã³ã®ããã©ãŒãã³ã¹ãç£èŠããŸããããã©ãŒãã³ã¹ãåäžãããããã«ã³ãŒããæé©åããŸãã
- ãããã€ãèªååãã: ã¢ããªã±ãŒã·ã§ã³ãšãã©ã°ã€ã³ã®ãããã€ãèªååããŸããããã«ããããšã©ãŒã®ãªã¹ã¯ãæžå°ããæŽæ°ãè¿ éã«ãããã€ãããããšãä¿èšŒãããŸãã
- äžè²«ããã³ãŒãã£ã³ã°ã¹ã¿ã€ã«ã䜿çšãã: ãã¹ãŠã®ãã©ã°ã€ã³ã§äžè²«ããã³ãŒãã£ã³ã°ã¹ã¿ã€ã«ã匷å¶ããŸããããã«ãããã³ãŒããèªã¿ããããä¿å®ãããããªããŸãã
- ãŠããããã¹ããäœæãã: ãã©ã°ã€ã³ãæ£ããåäœããããšã確èªããããã«ããŠããããã¹ããäœæããŸãã
- ãªã³ã¿ãŒã䜿çšãã: ã³ãŒãã®ãšã©ãŒãèªåçã«ãã§ãã¯ããããã«ãªã³ã¿ãŒã䜿çšããŸãã
çµè«
JavaScript Module Federationã¯ãåçãªãã©ã°ã€ã³ã·ã¹ãã ãæ§ç¯ããããã®åŒ·åã§æè»ãªã¡ã«ããºã ãæäŸããŸããModule FederationãæŽ»çšããããšã§ãå€åããèŠä»¶ã«é©å¿ã§ããã¢ãžã¥ãŒã«åŒã§ã¹ã±ãŒã©ãã«ããã€ä¿å®æ§ã®é«ãã¢ããªã±ãŒã·ã§ã³ãäœæã§ããŸãããã®èšäºã§æŠèª¬ãããã¹ããã©ã¯ãã£ã¹ã«åŸãããšã§ãçµç¹ã®ããŒãºãæºããå ç¢ã§å®å šãªãã©ã°ã€ã³ã·ã¹ãã ãæ§ç¯ã§ããŸãã
ãã®æè¡ã¯ç¹ã«åœéçãªæèã§äŸ¡å€ããããäŒæ¥ã¯å®å šã«å¥ã®ã¢ããªã±ãŒã·ã§ã³ããããã€ããããšãªããç¹å®ã®å°åã顧客ã»ã°ã¡ã³ãã«åãããŠãœãããŠã§ã¢æäŸã調æŽã§ããŸããããŒã«ã«ã®æ±ºæžã²ãŒããŠã§ã€ã®çµ±åããå°ååºæã®ã³ã³ãã³ãã®é ä¿¡ãŸã§ãModule Federationã¯ã°ããŒãã«ã§ããããŒãœãã©ã€ãºãããå¹ççãªãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãä¿é²ããŸãã